package com.gehj.uhttp.download;

import android.app.Activity;
import android.content.Context;

import androidx.annotation.NonNull;


import com.gehj.alluitls.DateUtil_gehj;
import com.gehj.alluitls.FileStorageManger;
import com.gehj.commonui.PrograssDialogUitl;
import com.gehj.uhttp.Singleton;
import com.gehj.uhttp.TokenInterceptor;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

import okhttp3.Call;
import okhttp3.Callback;
import okhttp3.FormBody;
import okhttp3.HttpUrl;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;

/**
  *
  * @ClassName:      HttpManger 下载类
  * @Description:    底层代码:利用OKhttp进行文件下载,保存到SD卡或者内存中;并且给自己定义的接口传值,方面UI中使用;
  * @Author:         gehj
  * @CreateDate:     2020/12/10 11:26
 */


public class HttpDownLoaderManger {
    public static final int NETWORK_ERROR_CODE = 1;
    public static final int CONTENT_LENGHT_ERROR_CODE = 2;
    public static final int TASK_RUNNING_ERROR_CODE = 3;
    private Context mContex;
    private OkHttpClient mClient;
    /*-----静态内部类实现 单例模式----------*/
    private static class Holder {
        private static final HttpDownLoaderManger MHTTP_DOWN_LOADER_MANGER = new HttpDownLoaderManger();
    }

    private HttpDownLoaderManger() {
        if (Holder.MHTTP_DOWN_LOADER_MANGER != null) {
            try {
                throw new IllegalAccessException("单例已经被实例化,请不要使用非法反射构造函数");
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
        }
        mClient = Singleton.getOkhttpClientInstance();
    }
    public static HttpDownLoaderManger getInstance() {
        return Holder.MHTTP_DOWN_LOADER_MANGER;
    }
    /*-----单例模式结束----------*/

    /**
     * 在MyAppliction中使用
     *  FileStorageManger.getInstance().init(this);//初始化文件管理;
     *  HttpManger.getInstance().init(this);
     * */
    public void init(Context context) {
        mContex = context;
    }

    public void getAsyncRequest(final String url, final Callback callback) {//get请求;
        Request request = new Request.Builder().url(url).build();
        mClient.newCall(request).enqueue(callback);
    }



    //下载文件:Transfer-Encoding:chunked:动态网页, 没有content-length字段;下载文件一类才有这个字段
    public void downLoadFile(String url, Callback callback) {//文件下载,未处理文件;
        Request request = new Request.Builder().url(url)
                .addHeader("Range", "bytes=0-7000").build();

        mClient.newCall(request).enqueue(callback);

    }

    /**
     * 好司机商户端下载文件- excel 在子线程下载
     * @param url
     * @param urlBuilder
     * @param context
     * @param prograssDialogUitl
     * @param callback
     */
    public void get_addParam_token_downLoadFile(String url, final HttpUrl.Builder urlBuilder,
                                                Context context, PrograssDialogUitl prograssDialogUitl,
                                                final DownLoadCallback callback) { //异步请求下载文件,处理了文件;

        final Request request =  new Request.Builder()
                .get()
                .url(urlBuilder.build())
                .build();

        mClient.newBuilder()
                .addInterceptor(new TokenInterceptor(mContex)).build()
               // .build()
                .newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) throws IOException {

                    ((Activity)context).runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                           if (null != prograssDialogUitl )prograssDialogUitl.dismissDialog();
                            //FuctionUtils.BackLogin(response,((Activity)context));
                        }
                    });


                    if (!response.isSuccessful() && callback != null) {
                        callback.fail(NETWORK_ERROR_CODE, "请求失败");
                        return;
                    }
                downLoadToFile_NoLegth(response, url, callback);

            }
        });

    }

    /**
     * 没有content-length字段的下载 excel文件
     * @param response
     * @param url
     * @param callback
     */
    private void downLoadToFile_NoLegth(Response response, String url, DownLoadCallback callback) {//输入流到文件;

        File file = FileStorageManger.getInstance().getFileByName("兑换记录"+
                DateUtil_gehj.date2Str(DateUtil_gehj.yyyymmddhhmmss)+".xls");

       // long fileLength = response.body().contentLength();

        byte[] buffer = new byte[1024];//缓存区域;
        int length;
        long readedLength = 0l;//进度读取条;
        //以下输出文件内容;
        InputStream inputStream = response.body().byteStream();
        FileOutputStream fileOutputStream = null;

        try {
            fileOutputStream = new FileOutputStream(file);
            while ((length = inputStream.read(buffer)) != -1) {//inputstream-->buffer
                fileOutputStream.write(buffer, 0, length);//buffer-->fileOutputStream=file
                readedLength += length;
               // curProgress = (int) (((float)readedLength/fileLength)*100);
               // callback.progress(curProgress);
            }
            fileOutputStream.flush();
            //fileOutputStream.flush();
            //if (readedLength==fileLength)  callback.success(file);
            callback.success(file);
            //downloadEntity.setSuccess(true);
            //downloadEntity.update(downloadEntity.getId());

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            cancelAllCall();
        }
    }




    /**
     * 普通下载 apk等：在子线程下载
     * @param url
     * @param callback
     */
    public void asyncRequestDownLoadFile(final String url, final DownLoadCallback callback) { //异步请求下载文件,处理了文件;

        final Request request = new Request.Builder().url(url).build();

        mClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {

            }

            @Override
            public void onResponse(Call call, Response response) {
                if (!response.isSuccessful() && callback != null) {
                    callback.fail(NETWORK_ERROR_CODE, "request failed");
                }

                downLoadToFile2(response, url, callback);
            }
        });

    }

    /**
     * 有content-length 可以走进度条的下载
     * @param response
     * @param url
     * @param callback
     */
    private void downLoadToFile(Response response, String url, DownLoadCallback callback) {//输入流到文件;
        int curProgress = 0;  //进度条的刻度值
        File file = FileStorageManger.getInstance().getFileByName("兑换记录"+
                DateUtil_gehj.date2Str(DateUtil_gehj.yyyymmddhhmmss)+".xls");
        long fileLength = response.body().contentLength(); //文件总长度



        byte[] buffer = new byte[1024];//缓存区域;
        int length;
        long readedLength = 0l;//进度读取条;
        //以下输出文件内容;
        InputStream inputStream = response.body().byteStream();
        FileOutputStream fileOutputStream = null;

        try {
            fileOutputStream = new FileOutputStream(file);
            while ((length = inputStream.read(buffer)) != -1) {//inputstream-->buffer
                fileOutputStream.write(buffer, 0, length);//buffer-->fileOutputStream=file
                readedLength += length;
                curProgress = (int) (((float)readedLength/fileLength)*100);
                callback.progress(curProgress);
            }
            fileOutputStream.flush();
            //downloadEntity.setProgress_pos(readedLength);//记录暂停前的数据;
            //fileOutputStream.flush();
            if (readedLength==fileLength)  callback.success(file);
                //downloadEntity.setSuccess(true);
           //downloadEntity.update(downloadEntity.getId());

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            cancelAllCall();
         }
    }


    /**
     * 不用OK的下载，没有测试
     *
     * @param urlBuilder
     * @param callback
     */
    private void download( HttpUrl.Builder urlBuilder, DownLoadCallback callback) {
        File file = FileStorageManger.getInstance().getFileByName("兑换记录"+
                DateUtil_gehj.date2Str(DateUtil_gehj.yyyymmddhhmmss)+".xls");
        byte[] bs = new byte[1024];
        int len;
        try {
            URL url = new URL(urlBuilder.build().toString());
            URLConnection conn = url.openConnection();
            InputStream is = url.openStream();
            OutputStream os = new FileOutputStream(file);
            while((len = is.read(bs)) != -1){
                os.write(bs,0,len);
            }

            os.close();
            is.close();

        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }


    }


    /**
     * //TODO 需要想办法获取下载类型，并建立file，如果服务端给类型的话，从最后的.(dot)分割判断文件类型
     * 下载apk等-没有content-length字段
     * @param response
     * @param url
     * @param callback
     */
    private void downLoadToFile2(Response response, String url, DownLoadCallback callback) {//输入流到文件;
        //DownloadEntity downloadEntity = getDownloadEntity(url);//单线程下载,只有一个实体类;

        File file = FileStorageManger.getInstance().getFileByName("gooddriver.apk");
        //long fileLength = response.body().contentLength();


        byte[] buffer = new byte[1024];//缓存区域;
        int length;
        long readedLength = 0l;//进度读取条;
        //以下输出文件内容;
        InputStream inputStream = response.body().byteStream();
        FileOutputStream fileOutputStream = null;

        try {
            fileOutputStream = new FileOutputStream(file);
            while ((length = inputStream.read(buffer)) != -1) {//inputstream-->buffer
                fileOutputStream.write(buffer, 0, length);//buffer-->fileOutputStream=file
                readedLength += length;
                //curProgress = (int) (((float)readedLength/fileLength)*100);
                //callback.progress(curProgress);
            }
            fileOutputStream.flush();
            //fileOutputStream.flush();
          //if (readedLength==fileLength)  callback.success(file);
              callback.success(file);

        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            if (fileOutputStream != null) {
                try {
                    fileOutputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            cancelAllCall();
        }
    }


    public  void cancelAllCall(){
        mClient.dispatcher().cancelAll();

    }

}
